package com.axend.aerosense.common.connect.tcp;

import com.axend.aerosense.base.utils.ByteUtils;
import com.axend.aerosense.common.connect.bean.MessageEntity;
import com.blankj.utilcode.util.LogUtils;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;

public class MessageCodec extends MessageToMessageCodec<ByteBuf, MessageEntity> {

    /**
     * 消息编码
     * @param ctx
     * @param msg
     * @param out
     * @throws Exception
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, MessageEntity msg, List<Object> out) throws Exception {
        byte[] bytes;
        switch (msg.getTag()){
            case getID:
            case getAlarmDelay:
            case getDeviceHeight:
            case getHardwareVersion:
            case getWorkDistance:
                bytes = MessageEntity.BodyState.getMessage.getBytes();
                break;
            case setDeviceIPAndPort:
                // 服务器ip和端口请用英文逗号分隔
                bytes = msg.getBodyObj().toString().getBytes();
                break;
            case setFamilyWifiInfo:
                // wifi账号和密码必须用英文逗号分隔
                bytes = msg.getBodyObj().toString().getBytes();
                break;
            default:
                bytes = msg.getBody();
                break;
        }

        ByteBuf buf = ctx.alloc().buffer();
        //添加头部
        buf.writeBytes(MessageEntity.MESSAGE_HEAD);
        //添加消息长度
        buf.writeBytes(ByteUtils.short2ByteLE((short) bytes.length));
        //添加消息标识
        buf.writeBytes(msg.getTag().getBytes());
        //添加消息体
        buf.writeBytes(bytes);

        byte[] b = new byte[buf.readableBytes()];
        buf.markReaderIndex();
        buf.readBytes(b);
        buf.resetReaderIndex();
        LogUtils.d("发送的原始数据：" + ByteUtils.bytesToHexString(b));

        out.add(buf);
    }

    /**
     * 消息解码
     * @param ctx
     * @param msg
     * @param out
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        LogUtils.d("消息解码...");

        byte[] bytes = new byte[msg.readableBytes()];
        msg.markReaderIndex();
        msg.readBytes(bytes);
        msg.resetReaderIndex();
        LogUtils.d("接收原始数据：" + ByteUtils.bytesToHexString(bytes));

        if (msg.readableBytes() < MessageEntity.MESSAGE_HEAD.length
                || !Arrays.equals(getBytes(msg, 4), MessageEntity.MESSAGE_HEAD)){
            LogUtils.w("Message not head");
            return;
        }

        MessageEntity entity = new MessageEntity();
        //获取消息标签
        entity.setTag(MessageEntity.MsgTag.get(msg.readShortLE()));
        //跳过长度两个字节
        msg.skipBytes(2);
        byte[] body = getBytes(msg, msg.readableBytes());
        //获取长度
        entity.setLength(body.length);
        //获取消息体
        entity.setBody(body);
        //将消息体转换成消息体对象
        entity.setBodyObj(getBodyObj(entity.getTag() ,body));
        out.add(entity);
    }

    /**
     * 把消息体中的字节数组转成对象
     * @param tag
     * @param body
     * @return
     */
    private Object getBodyObj(MessageEntity.MsgTag tag, byte[] body) {
        Object result = null;
        switch (tag){
            case setFamilyWifiInfo:
            case setAlarmDelay:
            case setDeviceHeight:
            case setWorkDistance:
            case setDeviceIPAndPort:
                result = Arrays.equals(MessageEntity.BodyState.setSuccess.getBytes(), body);
                break;
            case getID:
//                try {
//                    result = new String(body, "UTF-8");
//
//                } catch (UnsupportedEncodingException e) {
//                    e.printStackTrace();
//                }
                result = ByteUtils.bytesToHexString(body);
                break;
            case getAlarmDelay:
                result = ByteUtils.byteToInt(body);
                break;
            case getWorkDistance:
                result = ByteUtils.byteToFloat(body, 0);
                break;
            case getHardwareVersion:
                result = getHardwareVersionByString(body);
                break;
        }

        return result;
    }

    private byte[] getBytes(ByteBuf buf, int length){
        byte[] b = new byte[length];
        buf.readBytes(b);
        return b;
    }

    public String getHardwareVersionByString(byte[] bytes){
        LogUtils.d(bytes);
        LogUtils.d(ByteUtils.bytesToHexString(bytes));
        ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
        buffer.put(bytes);
        buffer.rewind();
        String str = "";
        //将每个字节转换成Int
        for (int i = 0; i < 4; i++){
            byte b = buffer.get();
            byte[] temp = new byte[4];
            temp[3] = b;
            //如果是个位数前补零
            String hexString = String.format("%02d", ByteUtils.byteToInt(temp));
            if (i == bytes.length -1){
                str += hexString;
            }else {
                str += hexString + ".";
            }
        }
        return str;
    }
}
